﻿/*
structure:  brief Definition of Structure class and Structure´s Aspects.
    Copyright (C) 2010  Jorge E. A. Atala
                        FuDePAN
    This file is part of the Biopp Proyect.

    Biopp is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Biopp is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Biopp.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef STRUCTURE_H
#define STRUCTURE_H

#include <vector>
#include <string>
#include "Atom.h"
#include "utils.h"

namespace biopp
{

typedef mili::bostream<mili::UnsafePolicy> bostream;
typedef mili::bistream<mili::UnsafePolicy> bistream;

template < class Item = Coord3d >
class Structure
{

protected:
    //the Item param should be Coord3 aspect from Atom.h file
    std::vector<Item> _item_vector;
public:

    inline Structure(size_t items) :
        _item_vector(items)
    {}

    inline Structure() :
        _item_vector()
    {}

    inline Structure(const Structure& other):
        _item_vector(other._item_vector)
    {}

    inline Structure(const std::vector<Item>& vector) :
        _item_vector(std::vector<Item>(vector))
    {}

    inline size_t items() const;

    inline void addItem(const Item& newItem);

    inline void setItem(const Item& newItem, size_t position);

    inline const Item& operator[](size_t index) const;

    inline Item& front();

    inline const Item& front() const;


};

// forward these

template < class A, class Item = Coord3d >
class Rotation_Aspect;

typedef Rotation_Aspect< Structure<> > StructureWithRotation;

inline bostream& operator<<(bostream& bos, const StructureWithRotation& structure);
inline bistream& operator>>(bistream& bis, StructureWithRotation& structure);

/*
 *  TODO: check concept syntax
 *  A Concept:
 *          vector<Item> item_vector
 *
 *          items()
 */

template<class A, class Item>
class Rotation_Aspect : public A
{
private:
    StructureID _id;

    void rotalign_to(const std::vector<Item>& reference);
public:

    inline Rotation_Aspect() :    // shouldn't use this constructor
        A(),
        _id(0)
    {}

    inline Rotation_Aspect(const A& structure) :
        A(structure),
        _id(0)
    {}

    inline Rotation_Aspect(StructureID id, size_t items):
        A(items),
        _id(id)
    {}

    inline Rotation_Aspect(const Rotation_Aspect& other):
        A(other),
        _id(other._id)
    {}

    inline Rotation_Aspect(const std::vector<Item>& vector, const StructureID& id):
        A(vector),
        _id(id)
    {}

    inline StructureID get_id() const;

    inline float rmsd_to(const Rotation_Aspect& b, bool useRotaling);
    float rmsd_to(const std::vector<Item>& b, bool useRotaling);

    inline void rotalign_to(const Rotation_Aspect& other);

    friend inline bostream& operator<<(bostream& bos, const StructureWithRotation& structure);
    friend inline bistream& operator>>(bistream& bis, StructureWithRotation& structure);

    //const bool operator<(Rotation_Aspect &otherStructure) const;
};

}

//To have cleaner code, inline functions are here
#define STRUCTURE_INLINE_H
#include "structure_inline.h"
#undef STRUCTURE_INLINE_H

#endif
